package project.parser.ast.types;

import project.environments.Value;
import project.parser.ast.exps.Ident;
import project.parser.ast.values.RecordValue;
import project.parser.tokenizer.TokenType;

import java.util.HashMap;
import java.util.Map;

public class RecordType implements Type {
	private Map<Ident,Type> typesMap;

	public RecordType(Map<Ident,Type> typesMap) {
		if (typesMap == null)
			typesMap = new HashMap<>();
		this.typesMap = typesMap;
	}

	public Map<Ident,Type> getTypesMap() {
		return new HashMap<>(typesMap);
	}

	public Type getFieldType(Ident fieldId) {
		return typesMap.get(fieldId);
	}

	public void setFieldType(Ident fieldId, Type fieldType) {
		if (typesMap.put(fieldId, fieldType) == null)
			throw new IllegalArgumentException("Field '" + fieldId + "' does not exist in this recordtype");
	}

	@Override
	public String toString() {
		return TokenType.RECORD_TYPE.toString();
	}

	@Override
	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || this.getClass() != o.getClass()) return false;
		RecordType that = (RecordType)o;
		return this.typesMap.equals(that.getTypesMap());
	}

	@Override
	public int hashCode() {
		return typesMap.hashCode();
	}

	public static RecordType createByValue(RecordValue recValue) {
		HashMap<Ident,Type> typesMap = new HashMap<>();
		for (Map.Entry<Ident,Value> field : recValue.asRecord().getValuesMap().entrySet())
			typesMap.put(field.getKey(), field.getValue().type());
		return new RecordType(typesMap);
	}

	public static boolean isInstance(Type type) {
		return type instanceof RecordType;
	}
}
